/**
 * Inventory file. Basically just a wrapper for a hashmap
 */
package edu.gatech.spacetraderteam3.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import edu.gatech.spacetraderteam3.debug.Debug;

/**
 * Inventory class for Resources. Basically just a wrapper class for a HashMap
 * with some extra functionality.
 * 
 * @author Aaron
 * @version 0.1
 */
public class Inventory implements Serializable {
    /**
     * The minimum number of items to hold
     */
    private static final int MIN_ITEMS = 10;

    /**
     * The fluxuation of price between goods
     */
    private static final int ITEM_VARIANCE = 10;

    /**
     * The serial Version UID for this Inventory (used in saving)
     */
    private static final long serialVersionUID = 8489624034180754863L;

    /**
     * The Actual Inventory (Resources -> Amount)
     */
    private HashMap<Resource, Integer> inv;

    /**
     * Constructor for inventory.
     */
    public Inventory() {
        inv = new HashMap<Resource, Integer>();
    }

    /**
     * Attempts to add the resource to the inventory.
     * 
     * @param res
     *            Resource being added.
     * @param amount
     *            Amount being added.
     * @return True if it was added correctly.
     */
    public boolean addResource(Resource res, int amount) {
        int theAmount = amount;
        if (inv.containsKey(res)) {
            theAmount += inv.get(res);
        }
        inv.put(res, theAmount);
        return true;
    }

    /**
     * Attempts to remove the resource from this inventory.
     * 
     * @param res
     *            Resource being removed.
     * @param amount
     *            Amount of it being removed.
     * @return True if it was removed, false otherwise
     */
    public boolean removeResource(Resource res, int amount) {
        if (!inv.containsKey(res)) {
            inv.put(res, 0);
        }
        final int i = inv.get(res);
        if (i - amount >= 0) {
            inv.put(res, i - amount);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Getter for number of Resource this inventory has.
     * 
     * @param res
     *            Resource in question.
     * @return Number of res's in this inventory.
     */
    public int getResource(Resource res) {
        return (inv.containsKey(res)) ? inv.get(res) : 0;
    }

    /**
     * Clears the inventory.
     */
    public void clear() {
        inv = new HashMap<Resource, Integer>();
    }

    /**
     * For when police search you for illegal substances(drugs and guns, apparently).
     * 
     * @return true if inventory has any guns or drugs in them currently.
     */
    public boolean hasContraband() {
        return (getResource(Resource.FIREARMS) > 0 || getResource(Resource.NARCOTICS) > 0);
    }

    /**
     * Populates the inventory with random goods.
     * 
     * @param contraband
     *            Whether to include contraband or not.
     */
    public void populate(boolean contraband) {
        final int numItems = (int) (Math.random() * ITEM_VARIANCE + MIN_ITEMS);
        for (int i = 0; i < numItems; i++) {
            Resource res = Resource.random();
            while (!contraband && (res == Resource.FIREARMS || res == Resource.NARCOTICS)) {
                res = Resource.random();
            }
            addResource(Resource.random(), 1);
        }
    }

    /**
     * Called when the player is looted by pirates.
     */
    public void becomeLooted() {
        final Set<Resource> resources = inv.keySet();
        final List<Resource> tor = new ArrayList<Resource>();
        for (Resource r : resources) {
            if (inv.get(r) <= 0) {
                tor.add(r);
            }
        }
        for (Resource r : tor) {
            resources.remove(r);
        }
        final int x = (int) (Math.random() * inv.size());
        final Resource looted = resources.toArray().length > 0 ? (Resource) resources.toArray()[x] : Resource.WATER;
        if (this.removeResource(looted, inv.get(looted) >> 1)) {
            Debug.write("Pirates looted you!", Debug.USER);
        }
    }

    /**
     * Gets a string made up of everything in the inventory
     * 
     * @return String of inventory's contents
     */
    public String toString() {
        return "Inventory with " + this.inv.toString();
    }

}
